home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * point.c
- *
- * This module implements the point & spot light source primitive.
- *
- * from Persistence of Vision(tm) Ray Tracer
- * Copyright 1996 Persistence of Vision Team
- *---------------------------------------------------------------------------
- * NOTICE: This source code file is provided so that users may experiment
- * with enhancements to POV-Ray and to port the software to platforms other
- * than those supported by the POV-Ray Team. There are strict rules under
- * which you are permitted to use this file. The rules are in the file
- * named POVLEGAL.DOC which should be distributed with this file. If
- * POVLEGAL.DOC is not available or for more info please contact the POV-Ray
- * Team Coordinator by leaving a message in CompuServe's Graphics Developer's
- * Forum. The latest version of POV-Ray may be found there as well.
- *
- * This program is based on the popular DKB raytracer version 2.12.
- * DKBTrace was originally written by David K. Buck.
- * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
- *
- *****************************************************************************/
-
- #include "frame.h"
- #include "vector.h"
- #include "povproto.h"
- #include "point.h"
- #include "matrices.h"
- #include "objects.h"
- #include "povray.h"
-
-
-
- /*****************************************************************************
- * Local preprocessor defines
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Local typedefs
- ******************************************************************************/
-
-
-
- /*****************************************************************************
- * Static functions
- ******************************************************************************/
-
- static DBL cubic_spline PARAMS(( DBL low,DBL high,DBL pos));
- static int All_Light_Source_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
- static int Inside_Light_Source PARAMS((VECTOR point, OBJECT *Object));
- static void Light_Source_Normal PARAMS((VECTOR Result, OBJECT *Object, INTERSECTION *Inter));
- static void Translate_Light_Source PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Rotate_Light_Source PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Scale_Light_Source PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
- static void Transform_Light_Source PARAMS((OBJECT *Object, TRANSFORM *Trans));
- static void Invert_Light_Source PARAMS((OBJECT *Object));
- static void *Copy_Light_Source PARAMS((OBJECT *Object));
- static void Destroy_Light_Source PARAMS((OBJECT *Object));
-
- /*****************************************************************************
- * Local variables
- ******************************************************************************/
-
- static METHODS Light_Source_Methods =
- {
- All_Light_Source_Intersections,
- Inside_Light_Source, Light_Source_Normal,
- Copy_Light_Source,
- Translate_Light_Source, Rotate_Light_Source,
- Scale_Light_Source, Transform_Light_Source, Invert_Light_Source,
- Destroy_Light_Source
- };
-
-
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * All_Light_Source_Intersections
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static int All_Light_Source_Intersections (Object, Ray, Depth_Stack)
- OBJECT *Object;
- RAY *Ray;
- ISTACK *Depth_Stack;
- {
- if (((LIGHT_SOURCE *)Object)->Children != NULL)
- {
- if (Ray_In_Bound (Ray, ((LIGHT_SOURCE *)Object)->Children->Bound))
- {
- if (All_Intersections (((LIGHT_SOURCE *)Object)->Children, Ray, Depth_Stack))
- {
- return(TRUE);
- }
- }
- }
-
- return(FALSE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Inside_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static int Inside_Light_Source (IPoint, Object)
- VECTOR IPoint;
- OBJECT *Object;
- {
- if (((LIGHT_SOURCE *)Object)->Children != NULL)
- {
- if (Inside_Object (IPoint, ((LIGHT_SOURCE *)Object)->Children))
- {
- return (TRUE);
- }
- }
-
- return (FALSE);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Light_Source_Normal
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Light_Source_Normal (Result, Object, Inter)
- OBJECT *Object;
- VECTOR Result;
- INTERSECTION *Inter;
- {
- if (((LIGHT_SOURCE *)Object)->Children != NULL)
- {
- Normal (Result, ((LIGHT_SOURCE *)Object)->Children,Inter);
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Translate_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Translate_Light_Source (Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- LIGHT_SOURCE *Light = (LIGHT_SOURCE *)Object;
-
- VAddEq (Light->Center, Vector);
- VAddEq (Light->Points_At, Vector);
-
- if (Light->Children != NULL)
- {
- Translate_Object (Light->Children, Vector, Trans);
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Rotate_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Rotate_Light_Source (Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Light_Source(Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Scale_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Scale_Light_Source (Object, Vector, Trans)
- OBJECT *Object;
- VECTOR Vector;
- TRANSFORM *Trans;
- {
- Transform_Light_Source(Object, Trans);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Transform_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Transform_Light_Source (Object, Trans)
- OBJECT *Object;
- TRANSFORM *Trans;
- {
- DBL len;
- LIGHT_SOURCE *Light = (LIGHT_SOURCE *)Object;
-
- MTransPoint (Light->Center, Light->Center, Trans);
- MTransPoint (Light->Points_At, Light->Points_At, Trans);
- MTransPoint (Light->Axis1, Light->Axis1, Trans);
- MTransPoint (Light->Axis2, Light->Axis2, Trans);
-
- MTransDirection (Light->Direction, Light->Direction, Trans);
-
- /* Make sure direction has unit length. */
-
- VLength(len, Light->Direction);
-
- if (len > EPSILON)
- {
- VInverseScaleEq(Light->Direction, len);
- }
-
- if (Light->Children != NULL)
- {
- Transform_Object (Light->Children, Trans);
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Invert_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Invert_Light_Source (Object)
- OBJECT *Object;
- {
- LIGHT_SOURCE *Light = (LIGHT_SOURCE *)Object;
-
- if (Light->Children != NULL)
- {
- Invert_Object (Light->Children);
- }
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- LIGHT_SOURCE *Create_Light_Source ()
- {
- int i;
- LIGHT_SOURCE *New;
-
- New = (LIGHT_SOURCE *)POV_MALLOC(sizeof (LIGHT_SOURCE), "light_source");
-
- INIT_OBJECT_FIELDS(New, LIGHT_OBJECT, &Light_Source_Methods)
-
- New->Children = NULL;
-
- Set_Flag(New, NO_SHADOW_FLAG);
-
- Make_Colour(New->Colour, 1.0, 1.0, 1.0);
- Make_Vector(New->Direction, 0.0, 0.0, 0.0);
- Make_Vector(New->Center, 0.0, 0.0, 0.0);
- Make_Vector(New->Points_At, 0.0, 0.0, 1.0);
- Make_Vector(New->Axis1, 0.0, 0.0, 1.0);
- Make_Vector(New->Axis2, 0.0, 1.0, 0.0);
-
- New->Coeff = 10.0;
- New->Radius = 0.35;
- New->Falloff = 0.35;
-
- New->Fade_Distance = 0.0;
- New->Fade_Power = 0.0;
-
- New->Next_Light_Source = NULL;
- New->Light_Grid = NULL;
- New->Shadow_Cached_Object = NULL;
-
- New->Light_Type = POINT_SOURCE;
-
- New->Area_Light = FALSE;
- New->Jitter = FALSE;
- New->Track = FALSE;
-
- New->Area_Size1 = 0;
- New->Area_Size2 = 0;
-
- New->Adaptive_Level = 100;
-
- New->Atmospheric_Attenuation = FALSE;
- New->Atmosphere_Interaction = TRUE;
-
- for (i = 0; i < 6; i++)
- {
- New->Light_Buffer[i] = NULL;
- }
-
- return (New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Copy_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void *Copy_Light_Source (Old)
- OBJECT *Old;
- {
- int i, j;
- LIGHT_SOURCE *New;
- LIGHT_SOURCE *Light = (LIGHT_SOURCE *)Old;
-
- New = Create_Light_Source();
-
- /* Copy light source. */
-
- *New = *(LIGHT_SOURCE *)Old;
-
- New->Next_Light_Source = NULL;
-
- New->Children = Copy_Object (((LIGHT_SOURCE *)Old)->Children);
-
- if (Light->Light_Grid != NULL)
- {
- New->Light_Grid = Create_Light_Grid(Light->Area_Size1, Light->Area_Size2);
-
- for (i = 0; i < Light->Area_Size1; i++)
- {
- for (j = 0; j < Light->Area_Size2; j++)
- {
- Assign_Colour(New->Light_Grid[i][j], Light->Light_Grid[i][j]);
- }
- }
- }
-
- return (New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Destroy_Light_Source
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static void Destroy_Light_Source (Object)
- OBJECT *Object;
- {
- int i;
- LIGHT_SOURCE *Light = (LIGHT_SOURCE *)Object;
-
- if (Light->Light_Grid != NULL)
- {
- for (i = 0; i < Light->Area_Size1; i++)
- {
- POV_FREE(Light->Light_Grid[i]);
- }
-
- POV_FREE(Light->Light_Grid);
- }
-
- Destroy_Object(Light->Children);
-
- POV_FREE(Object);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Create_Light_Grid
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- COLOUR **Create_Light_Grid (Size1, Size2)
- int Size1, Size2;
- {
- int i;
- COLOUR **New;
-
- New = (COLOUR **)POV_MALLOC(Size1 * sizeof (COLOUR *), "area light");
-
- for (i = 0; i < Size1; i++)
- {
- New[i] = (COLOUR *)POV_MALLOC(Size2 * sizeof (COLOUR), "area light");
- }
-
- return (New);
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * cubic_spline
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * Cubic spline that has tangents of slope 0 at x == low and at x == high.
- * For a given value "pos" between low and high the spline value is returned.
- *
- * CHANGES
- *
- * -
- *
- ******************************************************************************/
-
- static DBL cubic_spline(low, high, pos)
- DBL low, high, pos;
- {
- /* Check to see if the position is within the proper boundaries. */
-
- if (pos < low)
- {
- return(0.0);
- }
- else
- {
- if (pos >= high)
- {
- return(1.0);
- }
- }
-
- /* This never happens. [DB] */
-
- /*
- if (high == low)
- {
- return(0.0);
- }
- */
-
- /* Normalize to the interval [0...1]. */
-
- pos = (pos - low) / (high - low);
-
- /* See where it is on the cubic curve. */
-
- return(3 - 2 * pos) * pos * pos;
- }
-
-
-
- /*****************************************************************************
- *
- * FUNCTION
- *
- * Attenuate_Light
- *
- * INPUT
- *
- * OUTPUT
- *
- * RETURNS
- *
- * AUTHOR
- *
- * POV-Ray Team
- *
- * DESCRIPTION
- *
- * -
- *
- * CHANGES
- *
- * Jan 1995 : Added attenuation due to atmospheric scattering and light
- * source distance. Added cylindrical light source. [DB]
- *
- ******************************************************************************/
-
- DBL Attenuate_Light (Light, Ray, Distance)
- LIGHT_SOURCE *Light;
- RAY *Ray;
- DBL Distance;
- {
- DBL len, k, costheta;
- DBL Attenuation = 1.0;
- VECTOR P, V1;
-
- /* If this is a spotlight then attenuate based on the incidence angle. */
-
- switch (Light->Light_Type)
- {
- case SPOT_SOURCE:
-
- VDot(costheta, Ray->Direction, Light->Direction);
-
- costheta *= -1.0;
-
- if (costheta > 0.0)
- {
- Attenuation = pow(costheta, Light->Coeff);
-
- /*
- * If there is a soft falloff region associated with the light then
- * do an interpolation of values between the hot center and the
- * direction at which light falls to nothing.
- */
-
- if (Light->Radius > 0.0)
- {
- Attenuation *= cubic_spline(Light->Falloff, Light->Radius, costheta);
- }
- /*
- Debug_Info("Atten: %lg\n", Attenuation);
- */
- }
- else
- {
- Attenuation = 0.0;
- }
-
- break;
-
- case CYLINDER_SOURCE:
-
- VSub(V1, Ray->Initial, Light->Center);
-
- VDot(k, V1, Light->Direction);
-
- if (k > 0.0)
- {
- VLinComb2(P, 1.0, V1, -k, Light->Direction);
-
- VLength(len, P);
-
- if (len < Light->Falloff)
- {
- len = 1.0 - len / Light->Falloff;
-
- Attenuation = pow(len, Light->Coeff);
-
- if (Light->Radius > 0.0)
- {
- Attenuation *= cubic_spline(1.0 - Light->Radius / Light->Falloff, 1.0, len);
- }
- }
- else
- {
- Attenuation = 0.0;
- }
- }
- else
- {
- Attenuation = 0.0;
- }
-
- break;
- }
-
- if (Attenuation > 0.0)
- {
- /* Attenuate light due to light source distance. */
-
- if ((Light->Fade_Power > 0.0) && (fabs(Light->Fade_Distance) > EPSILON))
- {
- Attenuation *= 2.0 / (1.0 + pow(Distance / Light->Fade_Distance, Light->Fade_Power));
- }
- }
-
- return(Attenuation);
- }
-